# NO "#! /bin/bash" as we want to keep everything in scope
# 
# This should work in conjunction with tests
# CG 10/29/2005
#############################################################################

counterfail=0
counterpass=0
counterwarn=0
counterall=0
errorthreshold=25
testoutput="results" ; export $testoutput
teststatus=START
server=$defaultserver
validationservice="http://validator.w3.org/check"

#TODO: break these out to params that can be set. 
flags="-s --compressed -c cookies.txt -b cookies.txt -L -A QASHIZZLE $u_switch $authentic"


# Add this flag if you want to run your test through a local proxy. 
# (listening on port 8888 in this example)
# -x localhost:8888

# tty formatting codes for bringing attention to fail and warn results.
# single letter variables are nicer, because they make it easier to
# structure printf and echo output in multi-line statements (e.g.
# see results() function.

   r='\e[1;31m'  # red
   y='\e[33;1m'  # yellow
   n='\e[0m'     # no color

# following are compatibility names, because I have not yet updated all
# occurrences of these tty variables.

   red="${r}"
yellow="${y}"
    nc="${n}"

# [ "$DEBUG" = "true" ] && echo $flags
# [ "$DEBUG" = "true" ] && echo This is from functions.sh
#############################################################################

function testfail() {
	# any test can fail. 
	teststatus=FAIL
	counterfail=`expr $counterfail + 1`
	counterall=`expr $counterall + 1`
	echo -e ${red}"FAIL: ($counterall) $1"${nc}
	
	if [ $errorthreshold -ne '0' -a $counterfail -ge $errorthreshold ] ; then
		#echo TROUBLE
		testerror
	fi
}

function testpass() {
	if [ "$teststatus" != "FAIL" -a "$teststatus" != "WARN" ] ; then 
		teststatus=PASS
	fi
	counterpass=`expr $counterpass + 1`
	counterall=`expr $counterall + 1`
	echo "PASS: ($counterall) $1"
}

function testwarn() {
	if [ "$teststatus" != "FAIL" ] ; then 
		teststatus=WARN; 
	fi
	counterwarn=`expr $counterwarn + 1`
	counterall=`expr $counterall + 1`
	echo -e ${yellow}"WARN: ($counterall) $1"${nc}
}

function testerror() {
	teststatus=ERROR
	# TODO: do we halt?
	counterall=`expr $counterall + 1`	
	echo -e ${red}"ERROR: $1"${nc}
	echo $caller
	echo -e "${red}ERROR: ${nc}stopped testing after $errorthreshold failures. 
	Tests Run: $counterall
	Error threshold: $errorthreshold 
	"
	caller
	results
	exit 0
	# TODO: Maybe call results here? 	
}

function assert() {
	assertion="$1"
	if echo $response | grep -q "$assertion" ; then
	  testpass "$assertion"
	else
	  testfail "$assertion"
	fi
}

function assertWarn() {
	assertion="$1"
	if echo $response | grep -q "$assertion" ; then
	  testpass "$assertion"
	else
	  testwarn "$assertion"
	fi
}

# this for the negative case:
function assertNot() {
	assertion="$1"
	if echo $response | grep -qv "$assertion" ; then
	  testpass "$assertion not there"
	else
	  testfail "$assertion should not exist there"
	fi
}

#############################################################################
#
function getImage() {
	location=${1#"/"}
	# TODO: remove jpg assumption
	output_file=${2-"output.jpg"}
	echo "getImage http://$server/$location"
	`curl $flags "http://$server/$location" > $output_file`	
}

function getPage() {
	location=${1#"/"}
	echo "getPage http://$server/$location"
	response=`curl $flags -i "http://$server/$location"`
	# implicit assertion of 200 response. 
	# There's a -L in there so even if the first response is 302, we'll eventually hit a 200
	# TODO: This HTTP header is specific to HTTP/1.1, might neeed to genericize this. 
	assert "HTTP/1.1 200 OK"
}

function getPageMd5() {
        location=${1#"/"}
        echo "getPageMd5 http://$server/$location"
        response=`curl $flags "http://$server/$location" | md5sum`
        # presumes that you have a md5 hash for your response. 
        # To use it, you'll need to assert that hash. 
}

function getPage302() {
	# this is a bunch of BS
	# if there's a -L in $flags, this is kinda meaningless. 
	location=${1#"/"}
	echo "getRedirectPage $server/$location"
	response=`curl -s -k -L "$server/$location"`
	# need the -i anyway! 
	# assert "HTTP/1.1 302 OK" # no status message...
}


# FDA - April 04, 2006 
# postPage: takes any number of arguments (in the form of "<parameter>=<value>")
#           sends a curl request (post format) to the $server/$location for same.
#
# This is a little wacky, but we're using it for Login & Reg. 
# Maybe it's handy afterall and not eggregiously overengineered. 
#########################################################################
function postPage() {
	args=""
	post=""
	location=${1#"/"}
	# clear the $location from the arglist
	shift
	while [ "$#" -gt "0" ]; do
		# prepare post params
		args="$args -d $1"
		post="${post}${1}&"
	  	shift
	done 
	args="$args $flags"
	post=${post%"&"}
	echo "postPage http://$server/$location"
	echo "POST DATA: $post"
	echo
	response=`curl $args -i "http://$server/$location"`
	# echo $response
	assert "HTTP/1.1 200 OK"

}

function post302Page() {
	# This is relatively meaningless and likely not necessary at all. 
	args=""
	post=""
	location=${1#"/"}
	# clear the $location from the arglist
	shift
	while [ "$#" -gt "0" ]; do
		# prepare post params
		args="$args -d $1"
		post="${post}${1}&"
	  	shift
	done 
	args="$args $flags"
	post=${post%"&"}
	echo "postPage http://$server/$location"
	echo "POST DATA: $post"
	echo
	response=`curl $args -i "http://$server/$location"`
	# echo $response
	assert "HTTP/1.1 302"

}

function getXMLResponse() {
	location=${1#"/"}
	echo "getXMLResponse http://$server/$location"
	response=`curl $flags "http://$server/$location"`
	assert "HTTP/1.1 200 OK"
	# TODO: check that it's valid xml (xmlwf?)
	# TODO: Find a bash xml parser that'll let us do some xpath
}

function headPage() {
	location=${1#"/"}
	echo "page header for: http://$server/$location"
	response=`curl $flags -I "http://$server/$location"`
	assert "HTTP/1.1 200 OK"
}

function contentSize() {
	# This is slightly useless too... 
	location=${1#"/"}
	response=`curl $flags -I "http://$server/$location" | grep 'Content-Length:'`
	echo "$response"
}


#
# This section is nearly an abomination, but I see where it's leading. 
# Need to be able to dynamically get something from a page and use it
# in a later request. 
#
#
# for those tight spots that don't allow one to save into memory...KLUDGE!
# this function does what grep would not!
# I just want to be able to find : name=key value=<returnVal> pairs!
function getField() {
	echo adding $2 to $1
	$2=`echo $response | grep $1 | gawk '{ print $5 }'`
	# key="name=\"$1\""
	# keyLen=${#1}
	# echo "key=$key"
	# echo "keyLen=$keyLen"
	# value="$2="
 	# valLen=${#value}
	# echo "value=$value"
	# get past the first three args: getField <key> <value>
	# shift
	# shift
	# echo "\$1=$1"
	# shift # get past the header: just for kicks.
	# echo "\$1=$1"

	# while [[ -n "$1" && ! "$1" = $key ]]
	# do
		# shift through page until the key is found
		# echo "\$1=$1"
	#   	shift
	# done 
	# shift
	# response=${1:valLen}
	# clear quotes...
	# response=${response#"\""}
	# response=${response%"\""}
	# echo "response=$response"
}

# function getFieldValue() {
# 	response=`echo $response | grep "securityHash"`
# 	# echo "getFieldValue $1=$3 from the $2=$3 entry in a hidden field"
# 	echo "response=$response"
# 	response=${response%" />"} # clip off the last part.
# 	echo "response=$response"
# };

function validatePage() {
	echo "validatePage http://$server/${1#"/"}"
	runtime=`date +%s`
	datapackage=$testoutput/${1%\.*}$runtime
	[ ! -d "$testoutput" ] && mkdir "$testoutput"
# TODO: error checking for env. setup. Does the results dir exist? 
# TODO: functions for env setup! 
	validatethisfile=$datapackage-validatethis.htm
	echo Creating $validatethisfile
	curl $flags "http://$server/$1" > $validatethisfile
	
	validationresponse=`curl -s -F "uploaded_file=@$validatethisfile;type=text/html" $validationservice`
	#rm -rf ./$validatethisfile
	if echo $validationresponse | grep -q "checked and found to be valid"; then 
		testpass validatePagePASS
	elif echo $validationresponse | grep -q "Failed validation"; then
		testfail validatePageFAIL
		#Nerd reading the code: This is a hack. Assuming that the page name can be used here... 
		# TODO: more robust fillename handling
		failedPage=$datapackage-validationfailed.htm
		echo moving the test page, results to $failedPage
		echo $validationresponse > $failedPage
	else
		testwarn validatePageWARN
		warnPage=$datapackage-validationwarning.htm
		echo Warning, unknown response from the validator. Check $warnPage
		echo $validationresponse > $warnPage
	fi
	
	# w3c is shutting down repeated requests from a single ip. 
	# TODO: parameterize this. 
	sleep 5
}

function validateRedirectPage() {
	# TODO: justify this feature. 
	# Why did frank think that we need a separate function if the response is a redirect? 
	echo "validatePage http://$server/${1#"/"}"
	runtime=`date +%s`
	datapackage=$testoutput${1%\.*}$runtime
	dir=`ls . | grep $testoutput`
	[ ! -d "$testoutput" ] && mkdir "$testoutput"
	validatethisfile=$datapackage-validatethis.htm
	echo Creating $validatethisfile
	curl -s -k -L "$server/$1" > $validatethisfile
	validationresponse=`curl -s -F "uploaded_file=@$validatethisfile;type=text/html" http://validator.w3.org/check`
	#rm -rf ./$validatethisfile
	if echo $validationresponse | grep -q "checked and found to be valid"; then 
		testpass validatePagePASS
	elif echo $validationresponse | grep -q "Failed validation"; then
		testfail validatePageFAIL
		#Nerd reading the code: This is a hack. Assuming that the page name can be used here... 
		failedPage=$datapackage-validationfailed.htm
		echo moving the test page, results to $failedPage
		echo $validationresponse > $failedPage
	else
		#change this to testwarn at some point
		testwarn validatePageWARN
		warnPage=$datapackage-validationwarning.htm
		echo Warning, unknown response from the validator. Check $warnPage
		echo $validationresponse > $warnPage
	fi
}

# cookies
# toss the cookies. Or show them... Lots of work to do here... 
# 
# CG 12/01/2005
#############################################################################

function showCookies() {
	# TODO: error handling? 
	cat cookies.txt
}

function clearCookies() {
	echo removing cookies.txt
	rm -rf cookies.txt
	#
	# TODO: Plenty of good things to do here... 
	#  check whether it exists
	#  Move it to another location
	#  set up a restore function to bring it back... 
	#  Read the cookies...
}


# Usernames
# make (create), get (reuse)
# 
# FDA
#############################################################################
# put a sid down to shadow the current uname
# huh?
function putSid() {
	sid=1
	export sid
}
####!!! This function is semi-functional:
# get either a 2 or a 1 for speciesid into $sid
function getSid() {
	# what's the point of this function?  it's identical to putSid.
	sid=1
	export sid
}

# set the userFileName and sidFileName storage:
# TODO: fix this shizzle. 
function makeUserFileName() {
	userFile=tokenlog	
	userFileName="$userFile-$server.txt"

#
#	if [ `expr "$server" : "alpine-web06"` -gt 0 ] ; then
#		userFileName="$userFile-web06.txt"
# 	elif [ `expr "$server" : "taos"` -gt 0 ] ; then
# 		userFileName="$userFile-web08.txt"
#	elif [ `expr "$server" : "alpine-web05"` -gt 0 ] ; then
#		userFileName="$userFile-web05.txt"
#	elif [ `expr "$server" : "alpha-"` -gt 0 ] ; then
#		userFileName="$userFile-alpha.txt"
#	elif [ `expr "$server" : "journey-"` -gt 0 ] ; then
#		userFileName="$userFile-journey.txt"
#	elif [ `expr "$server" : "www.qa."` -gt 0 ] ; then
#		userFileName="$userFile-qa.txt"
#	else
#		userFileName="$userFile.txt"
#	fi
	export userFileName
}

function makeSidFileName() {
	sidFile=sidlog
	sidFileName=$sidFile-$server.txt
#
#	What was Frank thinking?
#	if [ `expr "$server" : "alpine-web06"` -gt 0 ] ; then
#		sidFileName="$sidFile-web06.txt"
# 	elif [ `expr "$server" : "taos"` -gt 0 ] ; then
# 		sidFileName="$sidFile-web08.txt"
#	elif [ `expr "$server" : "alpine-web05"` -gt 0 ] ; then
#		sidFileName="$sidFile-web05.txt"
#	elif [ `expr "$server" : "alpha-"` -gt 0 ] ; then 
#		sidFileName="$sidFile-alpha.txt"
#	elif [ `expr "$server" : "journey-"` -gt 0 ] ; then 
#		sidFileName="$sidFile-journey.txt"
#	elif [ `expr "$server" : "www.qa"` -gt 0 ] ; then 
#		sidFileName="$sidFile-qa.txt"		
#	else
#		sidFileName="$sidFile.txt"
#	fi
	export sidFileName
}

####################################################################################
# initialize servers and for some servers, initialize the authentication string.
# --> This is one very coupled / pasted function.
# ASSUME: the caller knows what server to send for images if a server is provided
#         via argument.
####################################################################################


# results
# toss out (echo) some data: passcounter, failcounter, testid, testname, testdescription
# 
# Maybe make this something that can easily be logged and grepped-for
# grep RES
# CG 11/15/2005
#
# FDA 04/04/2006
# * adding generic case for suite-level results...?
# * textual genericity (Results rather than "Test Results"
# * spacer: defined # of tabs for pretty print - April 23, 2006 
#
# spacer is a complete hack. There are formatting functions for this built into bash. 
# Need to handle warnings too. 
#
#############################################################################

# more half-baked crap from frank. 
function updateSuiteResults() {
	# TODO: get this working. Could be handy! 
	echo "fails so far: $counterfail"
	echo "passes so far: $counterpass"
	echo "warnings so far: $counterwarn"
	let "failCount+=$counterfail"
	let "passCount+=$counterpass"
	let "warnCount+=$counterwarn"

}

# setup the parameters to results and then call for (pretty) results
function getSuiteResults() {
	counterfail=$failCount
	counterpass=$passCount
	counterwarn=$warnCount
	testid="$1"
	testname="$2"
	warnResults
}

function results() {
	# TODO: Use padding functions. bash built-ins!
	passpct=`echo "scale = 2; $counterpass / $counterall * 100 " | bc`
	failpct=`echo "scale = 2; $counterfail / $counterall * 100 " | bc`
	warnpct=`echo "scale = 2; $counterwarn / $counterall * 100 " | bc`
	echo 
	echo "----------------------------------------------------------------------"
	echo Summary: $testid 
	echo Results: "$testname"
	printf     "TESTS: %3d\n"                 $counterall
	printf     "PASS:  %3d      %6.2f\n"      $counterpass  $passpct
	printf "${r}FAIL:  %3d      %6.2f${n}\n"  $counterfail  $failpct
	printf "${y}WARN:  %3d      %6.2f${n}\n"  $counterwarn  $warnpct
	echo "----------------------------------------------------------------------"
	# TODO: Clean this mess up. (reporting results)
	if [ "$counterfail" -gt "0" ]; then 
		reportresult="${red}$teststatus${nc}"
		#reportmessage="$counterpass passed, $counterfail failed. $counterwarn warn"
	else
		reportresult="$teststatus"
		#reportmessage="$counterpass passed, no failures"
	fi
		reportmessage="$counterpass pass, $counterfail fail, $counterwarn warn"
	echo -e RESULT: TC:$testid: $testname $reportresult "\t" $reportmessage
# 	 updateSuiteResults

}

